home *** CD-ROM | disk | FTP | other *** search
Text File | 1986-07-14 | 11.1 KB | 363 lines | [TEXT/MPS ] |
- UNIT OverView;
- {Version 1.0 Saturday, July 12, 1986 9:47:53 PM
- by Scott T. Boyd, the MacHax™ Group
- Many thanks to Greg Marriott of SoftWare To Go,
- also a member of the MacHax™ Group}
-
- {--------------------------------------------------------------------------}
- INTERFACE
-
- {Compiler Switch Settings}
- {$R+}
- {$OV+}
-
- uses MemTypes, QuickDraw, OSIntf, ToolIntf, SANE;
-
- const
- MenuBarHeight = 20; {Height of menu bar in pixels}
- TitleBarHeight = 18; {Height of window title bar in pixels}
- ScreenMargin = 4; {Width of "safety margin" around edge of screen}
- SBarHeight = 15; {Height of scroll bar}
- SBarWidth = 15; {Width of scroll bar}
-
- Procedure NewOverView( var OV_pagePict : bitMap;
- var OV : WindowPtr;
- viewRect : Rect;
- factor : Real );
- Procedure UpdateOverView( Procedure drawProc;
- OV_pagePict : bitMap);
- Procedure OverViewSelect( where: Point;
- viewRect : Rect; VAR scrollPosition : Point;
- VAR OV : WindowPtr; VAR OV_pagePict : bitMap;
- HScrollBar,VScrollBar : ControlHandle);
-
- {--------------------------------------------------------------------------}
- IMPLEMENTATION
- Procedure NewOverView {( var OV_pagePict : bitMap;
- var OV : WindowPtr;
- viewRect : Rect;
- factor : Real )};
- var
- dummyRect : Rect;
- horizontal, {horiz. pixel size of the OverView window}
- vertical : Extended; {vert. pixel size of the OverView window}
- sizeOfOff : Size; {bytes needed for offscreen bitmap}
- offRowBytes : Integer; {row bytes needed for offscreen bitmap}
- bitRect : Rect; {size of OV window and offscreen bitmap}
- dummy : Point;
- offPort, {temporary working port}
- oldPort : GrafPtr; {temporary storage}
- begin
- {compute available vertical screen space}
- vertical := ScreenBits.bounds.bottom-ScreenBits.bounds.top-MenuBarHeight;
- vertical := vertical * factor;
-
- {compute horizontal to proportion}
- horizontal := vertical * viewRect.right / viewRect.bottom;
-
- {create the new window record}
- SetRect(dummyRect,0,0,Num2Integer(horizontal),Num2Integer(vertical));
- OV := NewWindow( nil,dummyRect,'',FALSE,altDBoxProc,WindowPtr(-1),
- FALSE,LongInt(0) );
-
- {create offscreen bitmap}
- bitRect := OV^.portRect;
- offRowBytes := ((bitRect.right-bitRect.left) div 8) + 1;
- if Odd( offRowBytes ) then offRowBytes := offRowBytes - 1;
- sizeOfOff := (bitRect.bottom-bitRect.top) * offRowBytes;
- with OV_pagePict do
- begin
- baseAddr := QDPtr( NewPtr( sizeOfOff ));
- rowBytes := offRowBytes;
- bounds := bitRect;
- end;
-
- {fill the bitmap with white}
- GetPort( oldPort );
- offPort := GrafPtr( NewPtr( sizeof( GrafPort )));
- OpenPort( offPort );
- SetPortBits( OV_pagePict );
- FillRect( bitRect, white );
- SetPort( oldPort );
- ClosePort( offPort );
- DisposPtr( Ptr( offPort ));
- end; {MakeOverView}
-
- {--------------------------------------------------------------------------}
- Procedure UpdateOverView {( drawProc : Procedure;
- OV_pagePict : bitMap)};
- var
- offPort,
- oldPort : GrafPtr;
- begin
- GetPort( oldPort );
- offPort := GrafPtr( NewPtr( sizeof( GrafPort )));
- OpenPort( offPort );
- SetPortBits( OV_pagePict ); {make all drawing happen offscreen}
-
- drawProc; {let the user draw}
-
- SetPort( oldPort ); {return drawing to normal}
- ClosePort( offPort );
- DisposPtr( Ptr( offPort ));
- end; {UpdateOverView}
-
- {--------------------------------------------------------------------------}
- Procedure OverViewSelect{( where: Point;
- viewRect : Rect; VAR scrollPosition : Point;
- VAR OV : WindowPtr; VAR OV_pagePict : bitMap;
- HScrollBar,VScrollBar : ControlHandle)};
- var
- MenuFlash : ^Integer; {system global}
-
- value, {value returned by TrackGrayRgn}
- h, v : LongInt; {}
-
- pane, {}
- tempPt : Point; {}
-
- scope, {size of window pane scaled into OV window}
- tempRect,
- limitRect, {limit for drag region}
- slopRect : Rect; {slopiness allowance for dragging}
-
- dragRectRgn : RgnHandle; {the region the user drags around}
- oldPort : GrafPtr;
- theWindow : WindowPtr; {holds the value of frontWindow}
- underScope : BitMap; {dynamically allocated offscreen bitmap}
- whichWindow : WindowPtr; {for save and restore bits}
- {----------------------------------}
- Procedure OV_Prepare;
- begin
- MenuFlash := pointer($A24);
-
- GetPort( oldPort );
- theWindow := FrontWindow; {theWindow refers to the active window on entry}
- BringToFront( OV ); {make OV appear, but not really}
- SetPort( OV ); {it's now the current port}
- ShowHide( OV, FALSE ); {it's also not visible}
- MoveWindow( OV,0,0,FALSE ); {home the window}
-
- {compute the size of the current window pane}
- pane.h := theWindow^.portRect.right - theWindow^.portRect.left - sBarWidth;
- pane.v := theWindow^.portRect.bottom - theWindow^.portRect.top - sBarHeight;
-
- {scale the pane into the OV window to show size relative to document}
- SetRect( tempRect, 0, 0, pane.h, pane.v );
- MapRect( tempRect, viewRect, OV^.portRect );
- scope := tempRect;
-
- {make the region to drag around. same size as scope}
- dragRectRgn := NewRgn;
- RectRgn( dragRectRgn,scope );
-
- {believe it or not, this works to limit the movement of dragRectRgn}
- SetRect( limitRect, 0, 0, OV^.portRect.right-scope.right+1,
- OV^.portRect.bottom-scope.bottom+1 );
-
- {scale scrollPosition into OV for placing scope in OV}
- tempPt := scrollPosition;
- MapPt( tempPt, viewRect, OV^.portRect );
- OffSetRect( scope, tempPt.h, tempPt.v );
-
- end; {OV_Prepare}
- {----------------------------------}
- Procedure OV_PositionOverView;
- var offset : Point;
- begin
- SetPort( oldPort );
-
- offset := where;
- GlobalToLocal ( offset );
- h := offset.h; {this is the local value of the point of mousedown}
- v := offset.v;
-
- {make sure it doesn't go off the bottom of the window}
- if (v + OV^.portRect.bottom) >= theWindow^.portRect.bottom
- then v := theWindow^.portRect.bottom - OV^.portRect.bottom - 1;
- {make sure it doesn't go off the right of the window}
- if (h + OV^.portRect.right) >= theWindow^.portRect.right
- then h := theWindow^.portRect.right - OV^.portRect.right - 1;
- {make sure it doesn't go off the top of the window}
- if v < theWindow^.portRect.top then v := theWindow^.portRect.top;
- {make sure it doesn't go off the left of the window}
- if h < theWindow^.portRect.left then h := theWindow^.portRect.left;
-
- SetPt ( offset, h, v);
- LocalToGlobal( offset );
- h := offset.h;
- v := offset.v;
-
- SetPort( OV );
- MoveWindow( OV, h, v, FALSE );
- end; {OV_PositionOverView}
- {----------------------------------}
- procedure OV_SaveBits;
- var
- sizeOfOff : Size;
- offRowBytes : Integer;
- underRect,
- bitRect : Rect;
- dummy : Point;
- offPort,
- oldPort : GrafPtr;
- begin
- GetPort( oldPort );
-
- {put the window magager port into offport as a windowptr}
- GetWMgrPort( offPort );
- whichWindow := WindowPtr( offPort );
-
- {allocate a new grafport}
- offPort := GrafPtr( NewPtr( sizeof( GrafPort )));
-
- {home a copy of the bounds of the OV window}
- bitRect := OV^.portBits.bounds;
- offsetRect( bitRect, -bitrect.left, -bitrect.top );
-
- {compute memory necessary for offscreen bitmap}
- {allocate it and setup bitmap record}
- offRowBytes := ( bitRect.right div 8 ) + 1;
- if Odd( offRowBytes ) then offRowBytes := offRowBytes -1;
- sizeOfOff := bitRect.bottom * offRowBytes;
- with underScope do
- begin
- baseAddr := QDPtr( NewPtr( sizeOfOff ));
- rowbytes := offRowBytes;
- bounds := bitRect; {using HOMEd rectangle}
- end;
-
- {move a copy (to ensure no scaling occurs) back where OV will appear}
- underRect := underScope.bounds;
- OffsetRect( underRect, h-1, v-1 );
-
- {actually save the bits}
- OpenPort( offPort );
- SetPortBits( underScope );
- SetClip( offPort^.visRgn );
- CopyBits( whichWindow^.portBits, underScope,
- underRect, underScope.bounds,
- srcCopy, NIL);
- SetPort( oldPort );
- ClosePort( offPort );
- DisposPtr( Ptr( offPort ));
- end; {OV_SaveBits}
- {----------------------------------}
- Procedure OV_ShowOverView;
- var
- boxWidth,
- boxHeight: integer;
- begin
- OV_SaveBits;
- ShowHide( OV, TRUE ); {now the window appears}
-
- {blast miniature picture into OV}
- CopyBits(OV_pagePict, OV^.portBits,
- OV_pagePict.bounds, OV^.portRect,
- srcCopy,nil);
-
- {highlight the current selection}
- InvertRect( scope );
-
- {give the user some room to be sloppy}
- slopRect := OV^.portRect;
- InsetRect( slopRect, -25, -25 );
-
- GlobalToLocal( where );
-
- {compute size of the draggable region and center it on the cursor}
- boxWidth := scope.right - scope.left;
- boxHeight := scope.bottom - scope.top;
- OffsetRgn( dragRectRgn, where.h-(boxWidth div 2),
- where.v-(boxHeight div 2) );
- OffSetRect( limitRect, boxWidth div 2, boxHeight div 2);
-
- {let the user drag it around}
- value := DragGrayRgn( dragRectRgn,where,limitRect,slopRect,0,nil );
-
- end; {OV_ShowOverView}
- {----------------------------------}
- Procedure OV_RestoreBits;
- var underRect: Rect;
- begin
- underRect := underScope.bounds;
-
- {home the rectangle}
- OffsetRect( underRect, -underRect.left, -underRect.top);
-
- {position it correctly}
- OffSetRect( underRect, h-1, v-1);
-
- {blast stuff under window back into position}
- CopyBits( underScope, whichWindow^.portBits,
- underScope.bounds, underRect,
- srcCopy, NIL);
-
- {deallocate the bitmap space (be nice and clean)}
- DisposPtr( Ptr( underScope.baseAddr ));
- end; {OV_RestoreBits}
- {----------------------------------}
- Procedure OV_HandleSelection;
- {------------------------}
- Procedure OV_FlashSelection;
- var i: Integer;
- j: LongInt;
- begin
- HLock( Handle( dragRectRgn )); {try to make this a habit!}
- for i := 1 to 2*MenuFlash^ do begin
- InvertRect( dragRectRgn^^.rgnBBox );
- delay( 4,j );
- end;
- HUnLock( Handle( dragRectRgn )); {but don't forget this part}
- end;
- {------------------------}
- begin {OV_HandleSelection}
- if (HiWord(value)<>-32768) or (LoWord(value)<>-32768)
- then {user actually made a selection}
- begin
- InvertRect( scope ); {turn off current selection}
- OV_FlashSelection;
- ShowHide( OV, FALSE ); {hide the OV window}
- SetPort( oldPort );
- OV_RestoreBits; {blast bits back into place}
-
- {figure the new scrollPosition based on the top-left corner}
- {of the draggable region}
- SetPt( tempPt, dragRectRgn^^.rgnBBox.left, dragRectRgn^^.rgnBBox.top );
- MapPt( tempPt, OV^.portRect, viewRect );
- scrollPosition := tempPt;
-
- tempRect := viewRect;
- tempRect.bottom := tempRect.bottom - pane.v;
- tempRect.right := tempRect.right - pane.h;
- MapPt ( tempPt, tempRect, viewRect );
-
- {set the new scroll bar values}
- SetCtlValue( HScrollBar, tempPt.h );
- SetCtlValue( VScrollBar, tempPt.v );
- InvalRect( theWindow^.portRect );
- end
- else {no selection was made}
- begin
- ShowHide( OV, FALSE ); {hide the window}
- SetPort( oldPort );
- OV_RestoreBits; {replace the underneath bits}
- BeginUpdate( theWindow ); {steal the update events}
- EndUpdate ( theWindow );
- end;
- end; {OV_HandleSelection}
- {----------------------------------}
- Procedure OV_TidyUp;
- begin
- DisposeRgn( dragRectRgn );
- end; {OV_TidyUp}
- {----------------------------------}
- begin
- OV_Prepare;
- OV_PositionOverView;
- OV_ShowOverView;
- OV_HandleSelection;
- OV_TidyUp;
- end; {OverViewSelect}
-
- END. {UNIT OverView}